`timescale 1ns / 1ps
`include "defines.vh"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/06/12 10:56:26
// Design Name: 
// Module Name: MEM
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

// 访存模块
module MEM(
    input [0:0] clk,
    input [0:0] rst,




    //从ALU接收指令运算后数据
    input [`ALU_Parameter_BUS] ALU_Result,
    input [0:0] ALU_Carry,
    input [0:0] ALU_Overflow,

    



    //从CU接收写入寄存器相关数据
    input [0:0]  Write_Reg_from_ALU_Flag, //寄存器写数据由ALU得到 标志
    input [0:0] Write_Reg_from_CU_Flag, //寄存器写入值由CU得到 标志
    input [`Reg_Data_Bus] Write_Reg_from_CU_Data,




    input [0:0] Write_Reg_Flag_Input,  //寄存器写标志
    input [`Reg_Addr_Bus] Write_Reg_Addr_Input, //寄存器写地址

    input [0:0] RAM_Access_Flag_Input, //内存访问标志
    input [`RAM_Operation_BUS] RAM_Operation_Input,
    input [`RAM_Data_BUS] RAM_Write_Data_Input,

    // 发送到WB阶段

    //写寄存器
    output reg[0:0] Write_Reg_Flag_Output,  //寄存器写标志
    output reg[`Reg_Addr_Bus] Write_Reg_Addr_Output, //寄存器写地址
    output reg[`Reg_Data_Bus] Write_Reg_Data_Output //寄存器写值



    );


    wire [`Reg_Data_Bus] Write_Reg_Data_From_ALU;
    wire [`Reg_Data_Bus] Write_Reg_Data_From_RAM;

    always @(*) begin

        Write_Reg_Flag_Output = Write_Reg_Flag_Input;
        Write_Reg_Addr_Output = Write_Reg_Addr_Input;

        // 最终输出结果： Write_Reg_from_ALU_Flag   Write_Reg_from_CU_Flag  RAM_Operation_Input[3] 只会有一个是1
        Write_Reg_Data_Output =( {32{RAM_Operation_Input[3]}} & Write_Reg_Data_From_RAM) |({32{Write_Reg_from_ALU_Flag}}&Write_Reg_Data_From_ALU)| ({32{Write_Reg_from_CU_Flag}}&Write_Reg_from_CU_Data);            


    end


    assign Write_Reg_Data_From_ALU = (Write_Reg_from_ALU_Flag == `Write_reg_from_ALU_Enabled && Write_Reg_Flag_Input == `Write_Reg_Flag_Enabled) ? ALU_Result : `Zero32;
    
    







    always @(posedge clk) begin
        $display($time,"           MEM:  Write_Reg_Flag:%d,  Write_Reg_Addr:%d,  Write_Reg_Data:%d  ",Write_Reg_Flag_Output,Write_Reg_Addr_Output,$signed(Write_Reg_Data_Output));
        if(RAM_Access_Flag_Input == `RAM_Access_Flag_Enabled) begin
            $display($time,"           RAM:  access:%d,op:%d,data:%d,addr:%d",RAM_Access_Flag_Input,RAM_Operation_Input,$signed(RAM_Write_Data_Input),ALU_Result);
        end
    end

    RAM I_RAM(
        .rst(rst),
        .clk(clk),

        .RAM_Access_Flag_Input(RAM_Access_Flag_Input),
        .RAM_Operation_Input(RAM_Operation_Input),
        .RAM_Write_Data_Input(RAM_Write_Data_Input),
        .RAM_Addr_Input(ALU_Result),
        .RAM_Read_Data_Output(Write_Reg_Data_From_RAM)
    );








endmodule
